
import { getRoomDomain } from "../../../global/map";
import { roleTower } from "../../../role/tower";
import { timerEnd, timerStart } from "../../../util/log";
import { lookStructureCreation, step } from "../../../util/position";
import { StructureMap } from "../../../util/structure_map";
import { GroupCluster } from "./cluster";
import { ClusterConstructions } from "./constructions";

export class ClusterStructure extends GroupCluster{
    constructor(spawnRoom){
        super(spawnRoom);
        if(spawnRoom !== undefined){
            this.constructionGroup = new ClusterConstructions(spawnRoom);
        }
    }
    serialize(){
        return {
            super: super.serialize(),
        }
    }
    deserialize(obj){
        super.deserialize(obj.super);
        return this;
    }

    /**
     * 
     * @param {StructureMap} map 
     * @param {Structure[]} structures 
     * @returns {{towers:StructureTower[],links:StructureLink[],others:Structure[]}}
     */
    sortStructures(map, structures){
        let ans = {
            towers:[],
            links:[],
            coreLink:undefined,
            storeLink:undefined,
            others:[],
        }
        for(let structure of structures){
            switch(structure.structureType){
                case STRUCTURE_TOWER:
                    ans.towers.push(structure);
                    break;
                case STRUCTURE_LINK:
                    ans.links.push(structure);
                    let mem = Memory.structures[structure.id];
                    if(!mem){
                        Memory.structures[structure.id] = {};
                    }else{
                        if(mem.coreLink === true){
                            if(ans.coreLink === undefined){
                                ans.coreLink = structure;
                            }else{
                                ans.coreLink = null;
                                mem.coreLink = undefined;
                            }
                        }
                        if(mem.storeLink === true){
                            if(ans.storeLink === undefined){
                                ans.storeLink = structure;
                            }else{
                                ans.storeLink = null;
                                mem.storeLink = undefined;
                            }
                        }
                    }
                default:
                    ans.others.push(structure);
                    break;
            }
        }
        for(let link of ans.links){
            if(!ans.coreLink){
                Memory.structures[link.id].coreLink = undefined;
                if(!([TOP,LEFT,RIGHT,BOTTOM].some((direction)=>!lookStructureCreation(step(link.pos, direction))))){
                    ans.coreLink = link;
                    Memory.structures[link.id].coreLink = true;
                }
            }
            // if(!ans.storeLink){
            //     Memory.structures[link.id].storeLink = undefined;
            //     if(!([TOP,LEFT,RIGHT,BOTTOM].some((direction)=>!lookStructureCreation(step(link.pos, direction))))){
            //         ans.coreLink = link;
            //         Memory.structures[link.id].coreLink = true;
            //     }
            // }
        }
        return ans;
    }
    /**
     * 
     * @param {StructureMap} map 
     */
    run(map){
        if(!map){
            for(let structure of this.spawnRoom.find(FIND_MY_STRUCTURES,{filter:(structure)=>structure.isActive()})){
                if(structure instanceof StructureTower){
                    roleTower.run(structure);
                }
            }
            return OK;
        }
        let structures = this.sortStructures(map, this.spawnRoom.find(FIND_STRUCTURES,{
            filter(structure){
                return structure.isActive();
            }
        }));
        // timerStart();
        for(let structure of structures.towers){
            roleTower.run(structure);
        }
        // timerEnd();
        for(let structure of structures.others){
            if(structure instanceof StructureObserver){
                let domain = getRoomDomain(this.spawnRoom, false);
                structure.observeRoom(domain[Game.time%domain.length]);
            }
        }
    }
}